<template>
    <div>
        <div class="ManyToManyVideo" id="ManyToManyVideo">
            <video id="local" muted controls="controls"> </video>
            <div v-if="isCreateOfferOwner">
                <el-button type="primary" @click="shareScreenStream" round v-if="isLocalStream">分享屏幕</el-button>
                <el-button type="primary" @click="changeLocalStream" round v-if="!isLocalStream">切回主画面</el-button>
            </div>
        </div>
    </div>
</template>


<script>

    var PeerConnection = window.RTCPeerConnection ||
        window.mozRTCPeerConnection ||
        window.webkitRTCPeerConnection;
    export default {
    name: "ManyToManyVideoFrame",
    props:['socket','userInfo','chatTarget','groupUserList','isCreateOffer'],
    data(){
        return{
            localStream:'',//本地视频流
            isLocalStream:true,
            isCreateOfferOwner:true,
            userPeerList:[],//用户peer列表
            offerOption: {
                offerToReceiveAudio: 1,
                offerToReceiveVideo: 1
            },
            iceServers: {
                iceServers: [
                    { 
                        urls: "stun:stun.l.google.com:19302"
                    },
                    {
                        urls: 'turn:139.196.146.236:3478',
                        username: 'test',
                        credential: 'test123'
                    }
                ],
                sdpSemantics: 'unified-plan'
            }
        }
    },
    created() {
        console.log('重新初始化')
        this.init()
    },
    mounted() {

    },
    methods:{
        async init() {
            const that = this;
            await that.createNative();
            await that.nativeMedia();
            await that.initPeerList();
            await that.onListener();
            if(that.isCreateOffer){
               await that.onCreateOffer();
            }
        },
        // 测试TURN服务器连接
        testTurnServer() {
            const configuration = {
                iceServers: [
                    { 
                        urls: "stun:stun.l.google.com:19302"
                    },
                    {
                        urls: 'turn:139.196.146.236:3478',
                        username: 'test',
                        credential: 'test123'
                    }
                ]
            };
            
            console.log('测试TURN服务器连接...');
            
            const pc = new RTCPeerConnection(configuration);
            
            pc.onicecandidate = function(event) {
                if (event.candidate) {
                    console.log('候选类型:', event.candidate.type);
                    if (event.candidate.type === 'relay') {
                        console.log('*** 成功获取到relay候选，TURN服务器工作正常 ***');
                    }
                }
            };
            
            pc.oniceconnectionstatechange = function() {
                console.log('测试连接状态:', pc.iceConnectionState);
            };
            
            pc.createDataChannel('test');
            pc.createOffer().then(offer => {
                return pc.setLocalDescription(offer);
            }).then(() => {
                // 等待ICE候选收集
                setTimeout(() => {
                    console.log('TURN服务器测试完成');
                    pc.close();
                }, 10000); // 延长到10秒
            }).catch(err => {
                console.error('TURN测试错误:', err);
                pc.close();
            });
        },
        async initPeerList(){
            const that = this;
            // 初始化前先测试
            this.testTurnServer();
            that.userPeerList = [];
            let localUsername = that.userInfo.username;
            console.log("groupUserList->",that.groupUserList);
            that.groupUserList.forEach(ele=>{
                if(that.userInfo.username !== ele.username){
                    let peerName = localUsername+"-"+ele.username;
                    that.initPeer(peerName,ele);
                }
            });
            console.log(that.userPeerList)
        },
        //创建本地流全局放置
        async createNative() {
            const that = this;
            that.localStream = await this.createMedia()
        },
        // 本地摄像头打开
        nativeMedia(){
            const that = this;
            console.log("open local video",that.localStream)
            let video = document.querySelector('#local');
            // 旧的浏览器可能没有srcObject
            if ("srcObject" in video) {
                video.srcObject = that.localStream;
            } else {
                video.src = window.URL.createObjectURL(that.localStream);
                video.volume = 0
            }
            // eslint-disable-next-line no-unused-vars
            video.onloadedmetadata = function(e) {
                video.play();
            };
        },
        // 创建媒体流
        async createMedia() {
            const that = this;
            let streamTep = null;
            console.log("start prepare localStream origin")
            if( !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia ){
                that.$message.error("设备不支持")
                console.log('getUserMedia is not support!')
            }
                await navigator.mediaDevices.getUserMedia({audio: true, video: true})
                    .then(function (mediaStream) {
                    console.log("mediaStream",mediaStream)
                    streamTep = mediaStream;
                }).catch(error=>{
                    console.log("获取媒体设备异常",error)
                    that.$message.warning("获取媒体设备异常")
                })
            return streamTep;
        },
        //分享屏幕
        shareScreenStream(){
            const that = this;
            const displayMediaStreamConstraints = {
                video: {
                    cursor: "always"
                },
                audio: true
            };
            if (navigator.mediaDevices.getDisplayMedia) {
                navigator.mediaDevices.getDisplayMedia(displayMediaStreamConstraints).then(function (mediaStream) {
                    console.log("mediaStream", mediaStream)
                    that.shareStream = mediaStream;
                    that.groupUserList.forEach(ele=>{
                        if(that.userInfo.username !== ele.username){
                            let localUsername = that.userInfo.username;
                            let peerName = localUsername+"-"+ele.username;
                            that.userPeerList[peerName].removeStream(that.localStream)
                            that.userPeerList[peerName].addStream(mediaStream)
                        }
                    });
                    that.onCreateOffer();
                    let video = document.querySelector('#local');
                    if ("srcObject" in video) {
                        video.srcObject = that.shareStream;
                    } else {
                        video.src = window.URL.createObjectURL(that.shareStream);
                        video.volume = 0
                    }
                    // eslint-disable-next-line no-unused-vars
                    video.onloadedmetadata = function(e) {
                        video.play();
                    };
                    that.isLocalStream = false;
                }).catch(error=>{
                    console.log("error",error)
                    that.$message.error("媒体设备获取异常，请检查设备或浏览器是否支持")
                });
            } else {
                console.log("navigator.mediaDevices.getDisplayMedia  false");
                that.$message.error("浏览器不不支持")
                // navigator.getDisplayMedia(displayMediaStreamConstraints).then(success).catch(error);
            }
        },
        //切回本地摄像头
        changeLocalStream(){
            const that = this;
            that.shareStream.getTracks().forEach(track => track.stop());
            that.groupUserList.forEach(ele=>{
                        if(that.userInfo.username !== ele.username){
                            let localUsername = that.userInfo.username;
                            let peerName = localUsername+"-"+ele.username;
                            that.userPeerList[peerName].removeStream(that.shareStream)
                            that.userPeerList[peerName].addStream(that.localStream)
                        }
                    });
            that.onCreateOffer();
            that.nativeMedia();
            that.isLocalStream = true;
        },
        //追加视频
        createEleVideo(stream,id){
            console.log("createEleVideo",stream);
            let ele = document.getElementById("ManyToManyVideo");
            let old = document.getElementById(id);

            if(old){
                old.srcObject = stream;
            }else{
                let video = document.createElement('video');
                video.controls = true;
                video.autoplay = true;
                video.width = 230;
                video.height = 200;
                video.volume = 0.1;
                video.id = id;
                video.srcObject = stream;
                ele.append(video);
            }
        },
        //关闭本地画面
        closeNativeVideo(){
            let video = document.querySelector('#local');
            video.srcObject = null;
        },
        //挂断
        hangUp(){
            this.closeNativeVideo();
        },
        //移除视频
        removeEleVideo(eleId){
            document.getElementById("ManyToManyVideo").removeChild(document.getElementById(eleId));
        },
        //初始化 PeerConnection
        initPeer(peerName,e){
            const that = this;
            console.log(peerName+"初始化PeerConnection")
            let peer_tep = new PeerConnection(this.iceServers);
            peer_tep.addStream(that.localStream);

            // 添加 ICE 连接状态监控
            peer_tep.oniceconnectionstatechange = function() {
                console.log("[" + peerName + "] ICE 连接状态:", peer_tep.iceConnectionState);
                
                switch(peer_tep.iceConnectionState) {
                    case 'checking':
                        console.log("[" + peerName + "] 正在检查连接...");
                        break;
                    case 'connected':
                        console.log("[" + peerName + "] 已连接!");
                        break;
                    case 'completed':
                        console.log("[" + peerName + "] 连接完成!");
                        break;
                    case 'disconnected':
                        console.warn("[" + peerName + "] 连接断开，尝试重启ICE...");
                        // 可以尝试重启ICE
                        break;
                    case 'failed':
                        console.error("[" + peerName + "] 连接失败");
                        // 记录失败时的候选信息
                        break;
                }
            };

            peer_tep.onconnectionstatechange = function() {
                console.log("[" + peerName + "] 连接状态:", peer_tep.connectionState);
            };

            peer_tep.onicegatheringstatechange = function() {
                console.log("ICE 收集状态:", peer_tep.iceGatheringState);
            };

            // 在onicecandidate事件中添加检查relay候选
            peer_tep.onicecandidate = function(event) {
                console.log("监听ice候选信息", event.candidate);
                if (event.candidate) {
                    console.log("[" + peerName + "] 收集到候选:", {
                        type: event.candidate.type,
                        protocol: event.candidate.protocol,
                        address: event.candidate.address,
                        port: event.candidate.port
                    });
                    
                    // 特别关注relay类型候选
                    if (event.candidate.type === 'relay') {
                        console.log("[" + peerName + "] *** 收到RELAY候选，TURN服务器工作正常 ***");
                    }
                    
                    let candidate_data = {
                        userId: that.userInfo.userId,
                        username: that.userInfo.username,
                        candidate: event.candidate
                    };
                    let params = {
                        userId: that.userInfo.userId,
                        targetId: e.userId,
                        targetName: e.username,
                        targetType: 2,
                        data: candidate_data
                    };
                    that.socket.emit("candidate", params);
                } else {
                    console.log("[" + peerName + "] ICE收集已经完成");
                }
            };
            peer_tep.onaddstream = (event) => {
                console.log("监听到视频加入 加入用户 ",e.username)
                that.createEleVideo(event.stream,e.username)
            };
            that.userPeerList[peerName] = peer_tep;
        },
        //监听服务器信息
        onListener(){
            const that = this;
            that.socket.on("candidate",function (e) {
                console.log("服务器发送 candidate",e)
                that.onIceCandidate(e)
            })
            that.socket.on("offer",function (e) {
                console.log("服务器发送 offer",e)
                that.onOffer(e)
            })
            that.socket.on("answer",function (e) {
                console.log("服务器发送 answer",e)
                that.onAnswer(e)
            })
            that.socket.on("onJoinRoom",function (e) {
                console.log("服务器发送 onJoinRoom",e)
                that.$message.info("用户"+e.data.username+""+e.data.info)
                that.initPeerList();
            })
            that.socket.on("onLeftRoom",function (e) {
                console.log("服务器发送 onLeftRoom",e)
                that.$message.warning("用户"+e.data.username+"离开房间");
                that.removeEleVideo(e.data.username)
            })
        },
        //监听 Ice 候选
        async onIceCandidate(data) {
            const that = this;
            let peerName = that.userInfo.username+"-"+data.data.username;
            await that.userPeerList[peerName].addIceCandidate(data.data.candidate)
        },
        //监听远端offer
        async onOffer(data) {
            const that = this;
            let peerName = that.userInfo.username+"-"+data.data.username;
            console.log("接收到offer:",peerName)
            await that.userPeerList[peerName].setRemoteDescription(data.data.offer)
            // 接收端创建 answer
            let answer = await that.userPeerList[peerName].createAnswer();
            // 接收端设置本地 answer 描述
            await that.userPeerList[peerName].setLocalDescription(answer);
            //发送到呼叫端 answer
            let answer_data = {userId:that.userInfo.userId,username:that.userInfo.username,answer:answer}
            let params = {userId:that.userInfo.userId,targetId:data.data.userId,targetName:data.data.username,targetType:data.targetType,data:answer_data}
            that.socket.emit("answer",params)
        },
        //监听远程响应
        async onAnswer(data) {
            const that = this;
            let peerName = that.userInfo.username+"-"+data.data.username;
            // 发送端 设置远程 answer 描述
            await that.userPeerList[peerName].setRemoteDescription(data.data.answer);
        },
        //创建连接
        async onCreateOffer() {
            const that = this;
            console.log("开始创建offer")
            for(const ele of that.groupUserList){
                let peerName = that.userInfo.username+"-"+ele.username;
                if(that.userInfo.username !== ele.username){
                    //创建offer
                    let offer = await that.userPeerList[peerName].createOffer(that.offerOption);
                    //设置本地描述
                    await that.userPeerList[peerName].setLocalDescription(offer)
                    //远程发送到服务器 并转发到其他的客户端
                    let data = {offer:offer,userId:that.userInfo.userId,username:that.userInfo.username,info:"发送offer"}
                    let params = {userId:that.userInfo.userId,targetId:ele.userId,targetName:ele.username,targetType:2,data:data}
                    that.socket.emit("offer",params)
                }
            }
        },

    },
    watch:{

    },
    destroyed() {
        console.log("销毁子组件")
    }
}
</script>

<style scoped>

    .ManyToManyVideo{
        display: flow;
        width: 700px;
        background-color: rgba(201, 161, 169, 0.44);
    }
    .ManyToManyVideo video{
        object-fit:fill;
        width: 230px;
        height: 200px;
    }

</style>
